﻿using System.Collections.ObjectModel;
using System.Diagnostics;
using KinonekoSoftware.ArkSpark.Core.Delegates;
using KinonekoSoftware.ArkSpark.Documents;
using KinonekoSoftware.ArkSpark.Documents.Primitives;
using KinonekoSoftware.ArkSpark.Runtimes.Presenters;

namespace KinonekoSoftware.ArkSpark.Runtimes
{
    partial class ArkSparkMQ
    {
        private          IDocument                                         _Document;
        private readonly List<DocumentElement>                             _Elements;
        private readonly ObservableCollection<DocumentElementPresenter>    _ElementPresenters;
        private readonly ObservableCollection<DocumentElementPresenter>    _VisibleElements;
        private readonly Dictionary<Type, DocumentElementPresenterFactory> _FactoriesByType;

        private void InitializeFactories()
        {
            //
            // Internal Handler
            _FactoriesByType.Add(typeof(ParagraphElement), CreateParagraph);
            _FactoriesByType.Add(typeof(ReferenceElement), CreateReference);
            
            //
            // Derived Class Added Handler
            OnInitializeFactories(_FactoriesByType);
        }

        protected virtual void OnInitializeFactories(IDictionary<Type, DocumentElementPresenterFactory> mapper)
        {

        }

        #region Paragraph

        private DocumentElementPresenter CreateParagraph(DocumentElement element)
        {
            Debug.Assert(element is ParagraphElement);

            //
            //
            var element2 = (ParagraphElement)element;
            var presenter = new ParagraphPresenter(element2)
            {
                //
                //
                Bus = this,
            };


            ElementUpdatedEventArgs.OnNext(presenter, this);
            return presenter;
        }


        #endregion

        #region Reference

        private DocumentElementPresenter CreateReference(DocumentElement element)
        {
            Debug.Assert(element is ReferenceElement);

            //
            //
            var element2 = (ReferenceElement)element;
            var presenter = new ReferencePresenter(element2)
            {
                //
                //
                Bus = this,
            };


            return presenter;
        }



        #endregion

        #region Unknown

        private UnknownPresenter CreateUnknown(DocumentElement element)
        {
            Debug.Assert(element is not null);

            //
            //
            var presenter = new UnknownPresenter(element)
            {
                //
                //
                Bus = this,
            };


            return presenter;
        }

        #endregion

        public DocumentElementPresenter GetPresenter(DocumentElement element)
        {
            if (element is null)
            {
                Debug.WriteLine("元素为空");
                return null;
            }

            if (_FactoriesByType.TryGetValue(element.GetType(), out var factory))
            {
                //
                //
                Debug.Assert(factory is not null);

                //
                //
                var presenter = factory(element);

                //
                // 返回新的元素
                return presenter;
            }


            return CreateUnknown(element);
        }

    }
}